package com.egao.common.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.elasticsearch.entity.ElasticSearchConstants;
import com.egao.common.component.elasticsearch.service.ElasticSearchService;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.company.constants.AttachmentConstants;
import com.egao.common.module.company.constants.CheckRecordConstants;
import com.egao.common.module.company.constants.CompanyConstants;
import com.egao.common.module.company.constants.RecruitConstants;
import com.egao.common.module.company.entity.*;
import com.egao.common.module.company.entity.vo.CompanyListVO;
import com.egao.common.module.company.entity.vo.RecruitFormVO;
import com.egao.common.module.company.entity.vo.RecruitListVO;
import com.egao.common.module.company.mapper.RecruitMapper;
import com.egao.common.module.company.service.*;
import com.egao.common.module.company.utils.CompanyUtil;
import com.egao.common.module.push.constants.PushConstants;
import com.egao.common.module.push.entity.AbilityFormDTO;
import com.egao.common.module.push.entity.PushMsg;
import com.egao.common.module.push.service.PositionMatchingService;
import com.egao.common.module.push.service.PushMsgService;
import com.egao.common.module.pushInformation.service.PushInformationService;
import com.egao.common.module.system.constants.EmailConstants;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.service.DictService;
import com.egao.common.module.system.service.EmailService;
import com.egao.common.module.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * 招聘信息(Recruit)表服务实现类
 *
 * @author dl
 */
@Service
@Slf4j
public class RecruitServiceImpl extends ServiceImpl<RecruitMapper, Recruit> implements RecruitService {

    @Autowired
    private PositionService positionService;
    @Autowired
    private CompanyCheckRecordService companyCheckRecordService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private DictService dictService;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private ElasticSearchService elasticSearchService;
    @Resource(name = "taskRunnerExecutor")
    private ExecutorService asyncExecutorService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private UserService userService;
    @Resource
    private PushInformationService pushInformationService;

    @Override
    public List<RecruitListVO> listPage(PageParam<RecruitListVO> page) {
        // 申请时间
        page = (PageParam<RecruitListVO>) CompanyUtil.putApplyTime(page);
        Map<String, Object> map = page.getPageData();
        // 单位查询
        if (map.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) map.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            page.put("companyId", company.getId());
        }
        // 查询类型 岗位
        if (map.get(CompanyConstants.JOBS) != null) {
            String jobs = (String) map.get(CompanyConstants.JOBS);
            page.put("jobNameList", jobs.split("，"));
        }
        if (map.get(CompanyConstants.EDUCATION) != null) {
            String education = (String) map.get(CompanyConstants.EDUCATION);
            page.put("educationList", education.split("，"));
        }
        if (map.get(CompanyConstants.JOB_CATEGORY) != null) {
            String jobCategory = (String) map.get(CompanyConstants.JOB_CATEGORY);
            page.put("jobCategoryList", jobCategory.split("，"));
        }
        if (map.get(CompanyConstants.MAJORS) != null) {
            String majors = (String) map.get(CompanyConstants.MAJORS);
            page.put("majorsList", majors.split("，"));
        }
        return baseMapper.listPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult saveRecruit(RecruitFormVO recruitFormVO) {
        verifyRecruit(recruitFormVO);

        // 单位发布
        if (CompanyConstants.BUSINESS_TYPE_COMPANY.equals(recruitFormVO.getAddType())) {
            Company company = positionService.getCompanyByUserId(recruitFormVO.getCreateBy());
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            recruitFormVO.setCompanyId(company.getId());
            recruitFormVO.setCompanyName(company.getName());
        }

        // 复制招聘vo到实体
        Recruit recruit = new Recruit();
        copyRecruit(recruitFormVO, recruit);

        // 数据状态为有效的
        recruit.setInvalid(CompanyConstants.VALID);
        // 设置过期有效状态
        recruit.setOverdue("1");
        if (recruit.getValidTime() != null && recruit.getValidTime().getTime() > System.currentTimeMillis()) {
            recruit.setOverdue(CompanyConstants.VALID.toString());
        }

        // 保存招聘信息
        if (!save(recruit)) {
            return JsonResult.error("保存失败");
        }

        // 保存附件
        attachmentService.deleteAttach(recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
        attachmentService.saveAttach(recruitFormVO.getAttachments(), recruit.getId(), AttachmentConstants.TYPE_RECRUIT);

        // 单位发布的 保存精准匹配推荐信息
        if (CompanyConstants.ADD_TYPE_COMPANY.equals(recruit.getAddType())) {
            pushInformationService.save(recruit.getCompanyId(), 1, recruit.getId(), recruit.getTitle());
        }

        return JsonResult.ok("保存成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult updateRecruit(RecruitFormVO recruitFormVO) {
        Recruit recruit = getRecruitByFormVO(recruitFormVO);
        copyRecruit(recruitFormVO, recruit);
        //审核状态为待审核
        recruit.setState(CompanyConstants.RECRUIT_STATE_DSH);
        //数据状态为有效的
        recruit.setInvalid(CompanyConstants.VALID);

        if (updateById(recruit)) {
            attachmentService.deleteAttach(recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
            attachmentService.saveAttach(recruitFormVO.getAttachments(), recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult deleteRecruit(RecruitFormVO recruitFormVO) {
        verifyRecruit(recruitFormVO);

        if (recruitFormVO.getId() == null) {
            throw new ParameterException("招聘信息编号为空");
        }

        Recruit recruit = getById(recruitFormVO.getId());
        if (recruit == null) {
            throw new BusinessException("招聘信息为空");
        }

        // 设置招聘信息为失效
        recruit.setInvalid(CompanyConstants.RECRUIT_DELETED);

        if (updateById(recruit)) {
            String id = ElasticSearchConstants.INFORMATION_RECRUIT + "-" + recruit.getId();
            elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);

            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @Override
    public JsonResult detail(Integer id) {
        if (id == null) {
            throw new ParameterException("招聘信息编号为空");
        }

        Recruit recruit = getById(id);
        if (recruit == null) {
            throw new BusinessException("招聘信息不存在");
        }

        RecruitFormVO recruitFormVO = new RecruitFormVO();
        BeanUtil.copyProperties(recruit, recruitFormVO);

        // 单位发布需要查询职位
        if (recruit.getPositionIds() != null && CompanyConstants.ADD_TYPE_COMPANY.equals(recruit.getAddType())) {
            List<Position> positions = positionService.getPositionByIds(recruit.getPositionIds());
            if (positions != null && positions.size() > 0) {
                recruitFormVO.setPositions(positions);
            }
        }

        // 查询发布的附件
        List<Attachment> attachments = attachmentService.getAttachByBusinessId(id, AttachmentConstants.TYPE_RECRUIT);
        if (attachments != null && attachments.size() > 0) {
            recruitFormVO.setAttachments(attachments);
        }

        return JsonResult.ok("查询成功").setData(recruitFormVO);
    }

    // @Override
    // @Transactional(rollbackFor = Exception.class)
    // public JsonResult checkRecruit(RecruitFormVO recruitFormVO) {
    //     Recruit recruit = getRecruitByFormVO(recruitFormVO);
    //     String oldState = recruit.getState();
    //     copyRecruit(recruitFormVO, recruit);
    //     //数据状态为有效的
    //     recruit.setInvalid(CompanyConstants.VALID);
    //
    //     if (updateById(recruit)) {
    //         CompanyCheckRecord companyCheckRecord = new CompanyCheckRecord();
    //         companyCheckRecord.setCompanyId(recruit.getCompanyId());
    //         companyCheckRecord.setState(recruit.getState());
    //         companyCheckRecord.setStateContent(recruit.getStateContent());
    //         companyCheckRecord.setCheckUserId(recruitFormVO.getCheckUserId());
    //         companyCheckRecord.setType(CheckRecordConstants.CHECK_RECRUIT);
    //         companyCheckRecord.setBusinessId(recruit.getId());
    //         companyCheckRecordService.save(companyCheckRecord);
    //
    //         attachmentService.deleteAttach(recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
    //         attachmentService.saveAttach(recruitFormVO.getAttachments(), recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
    //
    //
    //         asyncExecutorService.submit((() -> {
    //             log.info("启动招聘信息推荐信息线程");
    //             long beginTime = System.currentTimeMillis();
    //             //需要发送邮件通知
    //             if(CompanyConstants.SUCCESS.equals(recruit.getEmailFlag()) && CompanyConstants.ADD_TYPE_SCHOOL.equals(recruit.getAddType())) {
    //                 //发送邮件
    //                 Company company = companyService.getById(recruit.getCompanyId());
    //                 if (company != null) {
    //                     User user = userService.getById(company.getUserId());
    //                     if (user != null) {
    //                         String[] email = {user.getUsername()};
    //                         emailService.sendTextEmail(EmailConstants.TITLE_RECRUIT_CHECK, recruit.getStateContent(), email);
    //                     }
    //                 }
    //             }
    //
    //             if (PushConstants.YES.equals(recruit.getPushFlag()) && CheckRecordConstants.CHECK_SUCCESS.equals(recruitFormVO.getState()) && CheckRecordConstants.CHECKING.equals(oldState)) {
    //                 pushMsgService.push(recruit.getId(), recruit.getTitle(), CheckRecordConstants.CHECK_RECRUIT, recruit.getCreateTime());
    //             }
    //
    //             // 保存es
    //             if (CheckRecordConstants.CHECK_SUCCESS.equals(recruit.getState())) {
    //                 String id = ElasticSearchConstants.INFORMATION_RECRUIT + "-" + recruit.getId();
    //                 elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
    //                 elasticSearchService.save(recruit);
    //             }
    //             long finishTime = System.currentTimeMillis();
    //             long overTime = (finishTime - beginTime) / 1000;
    //             log.info("完成招聘信息推荐信息线程任务：{} 秒", overTime);
            // }));
    //
    //         return JsonResult.ok("审核成功");
    //     }
    //     return JsonResult.error("审核失败");
    // }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult checkRecruit(RecruitFormVO recruitFormVO) {
        Recruit recruit = getRecruitByFormVO(recruitFormVO);
        copyRecruit(recruitFormVO, recruit);
        //数据状态为有效的
        recruit.setInvalid(CompanyConstants.VALID);

        // 设置过期有效状态
        if (recruit.getValidTime() != null && recruit.getValidTime().getTime() > System.currentTimeMillis()) {
            recruit.setOverdue(CompanyConstants.VALID.toString());
        } else {
            recruit.setOverdue("1");
        }

        if (updateById(recruit)) {
            CompanyCheckRecord companyCheckRecord = new CompanyCheckRecord();
            companyCheckRecord.setCompanyId(recruit.getCompanyId());
            companyCheckRecord.setState(recruit.getState());
            companyCheckRecord.setStateContent(recruit.getStateContent());
            companyCheckRecord.setCheckUserId(recruitFormVO.getCheckUserId());
            companyCheckRecord.setType(CheckRecordConstants.CHECK_RECRUIT);
            companyCheckRecord.setBusinessId(recruit.getId());
            companyCheckRecordService.save(companyCheckRecord);

            attachmentService.deleteAttach(recruit.getId(), AttachmentConstants.TYPE_RECRUIT);
            attachmentService.saveAttach(recruitFormVO.getAttachments(), recruit.getId(), AttachmentConstants.TYPE_RECRUIT);


            asyncExecutorService.submit((() -> {
                log.info("启动招聘信息推荐信息线程");
                long beginTime = System.currentTimeMillis();
                //需要发送邮件通知
                if(CompanyConstants.SUCCESS.equals(recruit.getEmailFlag()) && CompanyConstants.ADD_TYPE_SCHOOL.equals(recruit.getAddType())) {
                    //发送邮件
                    Company company = companyService.getById(recruit.getCompanyId());
                    if (company != null) {
                        User user = userService.getById(company.getUserId());
                        if (user != null) {
                            String[] email = {user.getUsername()};
                            emailService.sendTextEmail(EmailConstants.TITLE_RECRUIT_CHECK, recruit.getStateContent(), email);
                        }
                    }
                }

                // if (PushConstants.YES.equals(recruit.getPushFlag()) && CheckRecordConstants.CHECK_SUCCESS.equals(recruitFormVO.getState()) && CheckRecordConstants.CHECKING.equals(oldState)) {
                //     pushMsgService.push(recruit.getId(), recruit.getTitle(), CheckRecordConstants.CHECK_RECRUIT, recruit.getCreateTime());
                // }

                // 审核通过 更新推送信息
                if (CheckRecordConstants.CHECK_SUCCESS.equals(recruit.getState())) {
                    pushInformationService.checkPushState(1, recruit.getId());
                }

                // 保存es
                if (CheckRecordConstants.CHECK_SUCCESS.equals(recruit.getState())) {
                    String id = ElasticSearchConstants.INFORMATION_RECRUIT + "-" + recruit.getId();
                    elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
                    elasticSearchService.save(recruit);
                }
                long finishTime = System.currentTimeMillis();
                long overTime = (finishTime - beginTime) / 1000;
                log.info("完成招聘信息推荐信息线程任务：{} 秒", overTime);
            }));

            return JsonResult.ok("审核成功");
        }
        return JsonResult.error("审核失败");
    }


    @Override
    public JsonResult removeRecruit(RecruitFormVO recruitFormVO) {
        verifyRecruit(recruitFormVO);

        if (recruitFormVO.getId() == null) {
            throw new ParameterException("招聘信息编号为空");
        }

        Recruit recruit = getById(recruitFormVO.getId());
        if (recruit == null) {
            throw new BusinessException("招聘信息为空");
        }

        if (removeById(recruit)) {
            String id = ElasticSearchConstants.INFORMATION_RECRUIT + "-" + recruit.getId();
            elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @Override
    public void exportRecruit(PageParam<RecruitFormVO> page, HttpServletResponse response) {
        // 导出招聘数据
        List<RecruitFormVO> recruitFormVOList = baseMapper.listExcel(page);

        for (RecruitFormVO recruitFormVO : recruitFormVOList) {
            recruitFormVO.setNature(dictService.cacheLabel(CompanyConstants.NATURE_LIST_TYPE, recruitFormVO.getNature()));
            recruitFormVO.setIndustry(dictService.cacheLabel(CompanyConstants.INDUSTRY_LIST_TYPE, recruitFormVO.getIndustry()));
            recruitFormVO.setScale(dictService.cacheLabel(CompanyConstants.SCALE_LIST_TYPE, recruitFormVO.getScale()));
            if (RecruitConstants.TYPE_ONLINE.equals(recruitFormVO.getType())) {
                recruitFormVO.setType(RecruitConstants.TYPE_ONLINE_CONTENT);
            } else {
                recruitFormVO.setType(RecruitConstants.TYPE_INTERNSHIP_CONTENT);
            }
        }

        // 导出excel模板
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 设置别名和排序
        excelAddHeaderAlias(writer);

        // 写出内容 xlsx
        writer.write(recruitFormVOList, true);

        String fileName = "recruit-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=" + fileName);

        try {
            OutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (IOException e) {
            writer.close();
            log.error("导出失败 - StudentServiceImpl - exportStudent", e);
        } finally {
            writer.close();
        }
    }

    @Override
    public JsonResult getRecruitNumber(PageParam<RecruitListVO> page) {
        Map<String, Object> map = page.getPageData();
        // 单位查询
        if (map.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) map.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }

            if (CompanyConstants.RECRUIT_STATE.equals(company.getRecruitFlag())) {
                return JsonResult.ok("查询成功").setData(0);
            }
            page.put("companyId", company.getId());
        }
        Integer count = baseMapper.getRecruitByCompanyId(page);
        return JsonResult.ok("查询成功").setData(count);
    }

    @Override
    public JsonResult countRecruit(PageParam<RecruitListVO> page) {
        //申请时间
        page = (PageParam<RecruitListVO>) CompanyUtil.putApplyTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.getPageData().put("paramType", RecruitConstants.PARAMTYPE);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        Integer total = baseMapper.countTotal(page);
        List<Map<String, Object>> provinceList = baseMapper.countProvince(page);
        List<Map<String, Object>> natureList = baseMapper.countNature(page);
        List<Map<String, Object>> industryList = baseMapper.countIndustry(page);
        List<Map<String, Object>> scaleList = baseMapper.countScale(page);
        List<Map<String, Object>> addTypeList = baseMapper.countAddType(page);
        map.put("total", total);
        map.put("provinceList", provinceList);
        map.put("natureList", natureList);
        map.put("industryList", industryList);
        map.put("scaleList", scaleList);
        map.put("addTypeList", addTypeList);
        return JsonResult.ok().setData(map);
    }

    @Override
    public JsonResult countRecruitCategory(PageParam<RecruitListVO> page) {
        //申请时间
        page = (PageParam<RecruitListVO>) CompanyUtil.putApplyTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.getPageData().put("paramType", RecruitConstants.PARAMTYPE);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        List<Map<String, Object>> jobCategoryList = baseMapper.countJobCategory(page);
        map.put("jobCategoryList", jobCategoryList);
        return JsonResult.ok().setData(map);
    }

    @Override
    public JsonResult countRecruitEducation(PageParam<RecruitListVO> page) {
        //申请时间
        page = (PageParam<RecruitListVO>) CompanyUtil.putApplyTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.getPageData().put("paramType", RecruitConstants.PARAMTYPE);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        List<Map<String, Object>> educationList = baseMapper.countEducation(page);
        map.put("educationList", educationList);
        return JsonResult.ok().setData(map);
    }

    /** 
     * 验证招聘表单是否为空
     * @param recruitFormVO 招聘表单
     * @return 
     */
    private void verifyRecruit(RecruitFormVO recruitFormVO) {
        if (recruitFormVO == null) {
            throw new ParameterException("招聘信息为空");
        }
    }

    /**
     * 验证招聘表单是否为空，赋值
     * @param recruitFormVO 招聘表单
     * @param recruit 招聘实体
     * @return
     */
    private void copyRecruit(RecruitFormVO recruitFormVO, Recruit recruit) {
        BeanUtil.copyProperties(recruitFormVO, recruit);
        Date validTime = recruit.getValidTime();
        //设置到期时间为23:59:59
        validTime = DateUtil.offsetHour(validTime, 23);
        validTime = DateUtil.offsetMinute(validTime, 59);
        validTime = DateUtil.offsetSecond(validTime, 59);
        recruit.setValidTime(validTime);
    }

    /**
     * 获取需要修改招聘信息
     * @param recruitFormVO 招聘表单
     * @return
     */
    private Recruit getRecruitByFormVO(RecruitFormVO recruitFormVO) {
        verifyRecruit(recruitFormVO);

        if (recruitFormVO.getId() == null) {
            throw new ParameterException("招聘信息编号为空");
        }

        Recruit recruit = getById(recruitFormVO.getId());
        if (recruit == null) {
            throw new BusinessException("招聘信息为空");
        }

        return recruit;
    }

    /**
     * 为导出对象设置别名和排序 排序顺序为add顺序
     * @param writer ExcelWriter
     */
    public void excelAddHeaderAlias(ExcelWriter writer) {
        writer.addHeaderAlias("title", "标题");
        writer.addHeaderAlias("type", "招聘类型");
        writer.addHeaderAlias("jobName", "岗位名称");
        writer.addHeaderAlias("jobCategory", "岗位类型");
        writer.addHeaderAlias("number", "招聘人数");
        writer.addHeaderAlias("validTime", "有效期");
        writer.addHeaderAlias("area", "工作地点");
        writer.addHeaderAlias("majors", "相关专业");
        writer.addHeaderAlias("education", "学历限制");
        writer.addHeaderAlias("companyName", "招聘单位");
        writer.addHeaderAlias("nature", "单位性质");
        writer.addHeaderAlias("industry", "单位行业");
        writer.addHeaderAlias("scale", "单位规模");
        writer.addHeaderAlias("province", "所在省");
        writer.addHeaderAlias("city", "所在市");
        writer.addHeaderAlias("recruitContact", "联系人");
        writer.addHeaderAlias("recruitMobile", "联系电话");
    }
}
